/// 视频集合API服务
/// 
/// 提供视频集合相关的网络请求方法
/// 
/// @author Matrix
/// @version 1.0.0
/// @since 2025-11-26

import 'dart:io';
import 'package:dio/dio.dart';
import 'package:base_flutter/src/network/manager.dart';
import '../models/collection_model.dart';
import '../utils/logger.dart';
import 'api_service.dart';

/// 视频集合服务类
class CollectionService {
  /// 单例模式
  static final CollectionService _instance = CollectionService._internal();
  factory CollectionService() => _instance;
  CollectionService._internal();

  /// 网络管理器
  final NetworkManager _networkManager = NetworkManager();

  /// API基础路径
  static const String _basePath = '/api/collections';

  // ==================== 集合管理 ====================

  /// 创建视频集合
  /// 
  /// [title] 集合标题
  /// [description] 集合描述
  /// [coverUrl] 封面图URL
  /// [categoryId] 分类ID
  /// [categoryName] 分类名称
  /// [tags] 标签列表
  /// [accessType] 访问类型：public/whitelist
  /// [status] 状态：draft/published
  /// 
  /// 返回创建的集合ID
  Future<int> createCollection({
    required String title,
    String? description,
    String? coverUrl,
    String? categoryId,
    String? categoryName,
    List<String>? tags,
    String accessType = 'public',
    String status = 'draft',
  }) async {
    Logger.d('COLLECTION_SERVICE', '创建视频集合: $title');

    final response = await _networkManager.post(
      _basePath,
      data: {
        'title': title,
        'description': description,
        'coverUrl': coverUrl,
        'categoryId': categoryId,
        'categoryName': categoryName,
        'tags': tags,
        'accessType': accessType,
        'status': status,
      },
    );

    if (response['code'] == 200) {
      final collectionId = response['data']['collectionId'] as int;
      Logger.d('COLLECTION_SERVICE', '创建成功，集合ID: $collectionId');
      return collectionId;
    } else {
      throw Exception(response['message'] ?? '创建集合失败');
    }
  }

  /// 更新视频集合
  Future<void> updateCollection({
    required int id,
    String? title,
    String? description,
    String? coverUrl,
    String? categoryId,
    String? categoryName,
    List<String>? tags,
    String? accessType,
    String? status,
  }) async {
    Logger.d('COLLECTION_SERVICE', '更新视频集合: $id');

    final data = <String, dynamic>{'id': id};
    if (title != null) data['title'] = title;
    if (description != null) data['description'] = description;
    if (coverUrl != null) data['coverUrl'] = coverUrl;
    if (categoryId != null) data['categoryId'] = categoryId;
    if (categoryName != null) data['categoryName'] = categoryName;
    if (tags != null) data['tags'] = tags;
    if (accessType != null) data['accessType'] = accessType;
    if (status != null) data['status'] = status;

    final response = await _networkManager.put(_basePath, data: data);

    if (response['code'] != 200) {
      throw Exception(response['message'] ?? '更新集合失败');
    }
    Logger.d('COLLECTION_SERVICE', '更新成功');
  }

  /// 删除视频集合
  Future<void> deleteCollection(int collectionId) async {
    Logger.d('COLLECTION_SERVICE', '删除视频集合: $collectionId');

    final response = await _networkManager.delete('$_basePath/$collectionId');

    if (response['code'] != 200) {
      throw Exception(response['message'] ?? '删除集合失败');
    }
    Logger.d('COLLECTION_SERVICE', '删除成功');
  }

  /// 获取集合详情
  Future<CollectionModel> getCollectionDetail(int collectionId) async {
    Logger.d('COLLECTION_SERVICE', '获取集合详情: $collectionId');

    final response = await _networkManager.get('$_basePath/$collectionId');

    if (response['code'] == 200) {
      final data = response['data'] as Map<String, dynamic>;
      return CollectionModel.fromJson(data);
    } else {
      throw Exception(response['message'] ?? '获取集合详情失败');
    }
  }

  /// 获取我的集合列表
  /// 
  /// [page] 页码
  /// [pageSize] 每页数量
  /// [status] 状态筛选（可选）
  Future<PageResult<CollectionModel>> getMyCollections({
    int page = 1,
    int pageSize = 20,
    String? status,
  }) async {
    Logger.d('COLLECTION_SERVICE', '获取我的集合列表: page=$page, status=$status');

    final params = <String, dynamic>{
      'page': page,
      'pageSize': pageSize,
    };
    if (status != null) params['status'] = status;

    final response = await _networkManager.get('$_basePath/my', params: params);

    if (response['code'] == 200) {
      final data = response['data'] as Map<String, dynamic>;
      final records = (data['records'] as List)
          .map((e) => CollectionModel.fromJson(e as Map<String, dynamic>))
          .toList();
      return PageResult(
        records: records,
        total: data['total'] as int,
        current: data['current'] as int,
        pages: data['pages'] as int,
      );
    } else {
      throw Exception(response['message'] ?? '获取集合列表失败');
    }
  }

  /// 获取授权给我的集合列表（可享资源）
  /// 
  /// [page] 页码
  /// [pageSize] 每页数量
  Future<PageResult<CollectionModel>> getSharedCollections({
    int page = 1,
    int pageSize = 20,
  }) async {
    Logger.d('COLLECTION_SERVICE', '获取授权集合列表: page=$page');

    final params = <String, dynamic>{
      'page': page,
      'pageSize': pageSize,
    };

    final response = await _networkManager.get('$_basePath/shared', params: params);

    if (response['code'] == 200) {
      final data = response['data'] as Map<String, dynamic>;
      final records = (data['records'] as List)
          .map((e) => CollectionModel.fromJson(e as Map<String, dynamic>))
          .toList();
      return PageResult(
        records: records,
        total: data['total'] as int,
        current: data['current'] as int,
        pages: data['pages'] as int,
      );
    } else {
      throw Exception(response['message'] ?? '获取授权集合列表失败');
    }
  }

  /// 获取公开的集合列表
  Future<PageResult<CollectionModel>> getPublicCollections({
    int page = 1,
    int pageSize = 20,
    String? categoryId,
    String? keyword,
  }) async {
    Logger.d('COLLECTION_SERVICE', '获取公开集合列表: page=$page');

    final params = <String, dynamic>{
      'page': page,
      'pageSize': pageSize,
    };
    if (categoryId != null) params['categoryId'] = categoryId;
    if (keyword != null) params['keyword'] = keyword;

    final response = await _networkManager.get('$_basePath/public', params: params);

    if (response['code'] == 200) {
      final data = response['data'] as Map<String, dynamic>;
      final records = (data['records'] as List)
          .map((e) => CollectionModel.fromJson(e as Map<String, dynamic>))
          .toList();
      return PageResult(
        records: records,
        total: data['total'] as int,
        current: data['current'] as int,
        pages: data['pages'] as int,
      );
    } else {
      throw Exception(response['message'] ?? '获取集合列表失败');
    }
  }

  /// 获取推荐的集合列表
  Future<List<CollectionModel>> getRecommendedCollections({int limit = 10}) async {
    Logger.d('COLLECTION_SERVICE', '获取推荐集合列表: limit=$limit');

    final response = await _networkManager.get(
      '$_basePath/recommended',
      params: {'limit': limit},
    );

    if (response['code'] == 200) {
      final data = response['data'] as List;
      return data
          .map((e) => CollectionModel.fromJson(e as Map<String, dynamic>))
          .toList();
    } else {
      throw Exception(response['message'] ?? '获取推荐集合失败');
    }
  }

  /// 检查VIP状态
  Future<bool> checkVipStatus() async {
    Logger.d('COLLECTION_SERVICE', '检查VIP状态');

    final response = await _networkManager.get('$_basePath/check-vip');

    if (response['code'] == 200) {
      return response['data']['isVip'] as bool? ?? false;
    }
    return false;
  }

  /// 开通VIP（第一版：直接开通，跑通流程）
  /// 
  /// 正式版本需要接入支付系统
  Future<void> activateVip() async {
    Logger.d('COLLECTION_SERVICE', '开通VIP');

    final response = await _networkManager.post('$_basePath/activate-vip');

    if (response['code'] != 200) {
      throw Exception(response['message'] ?? '开通VIP失败');
    }
    Logger.d('COLLECTION_SERVICE', 'VIP开通成功');
  }

  // ==================== 视频管理 ====================

  /// 添加视频到集合
  /// 
  /// 返回视频ID
  Future<int> addVideo({
    required int collectionId,
    required String videoUrl,
    String? title,
    String? description,
    String? coverUrl,
    int? durationSec,
    int? orderNo,
  }) async {
    Logger.d('COLLECTION_SERVICE', '添加视频到集合: $collectionId');

    final response = await _networkManager.post(
      '$_basePath/videos',
      data: {
        'collectionId': collectionId,
        'videoUrl': videoUrl,
        'title': title,
        'description': description,
        'coverUrl': coverUrl,
        'durationSec': durationSec,
        'orderNo': orderNo,
      },
    );

    if (response['code'] == 200) {
      final videoId = response['data']['videoId'] as int;
      Logger.d('COLLECTION_SERVICE', '添加成功，视频ID: $videoId');
      return videoId;
    } else {
      throw Exception(response['message'] ?? '添加视频失败');
    }
  }

  /// 更新视频信息
  Future<void> updateVideo({
    required int videoId,
    String? title,
    String? description,
    String? coverUrl,
  }) async {
    Logger.d('COLLECTION_SERVICE', '更新视频: $videoId');

    // 构建查询参数字符串
    final queryParts = <String>[];
    if (title != null) queryParts.add('title=${Uri.encodeComponent(title)}');
    if (description != null) queryParts.add('description=${Uri.encodeComponent(description)}');
    if (coverUrl != null) queryParts.add('coverUrl=${Uri.encodeComponent(coverUrl)}');
    
    final queryString = queryParts.isNotEmpty ? '?${queryParts.join('&')}' : '';

    final response = await _networkManager.put(
      '$_basePath/videos/$videoId$queryString',
    );

    if (response['code'] != 200) {
      throw Exception(response['message'] ?? '更新视频失败');
    }
  }

  /// 删除视频
  Future<void> deleteVideo(int videoId) async {
    Logger.d('COLLECTION_SERVICE', '删除视频: $videoId');

    final response = await _networkManager.delete('$_basePath/videos/$videoId');

    if (response['code'] != 200) {
      throw Exception(response['message'] ?? '删除视频失败');
    }
  }

  /// 获取集合的视频列表
  Future<List<CollectionVideoModel>> getCollectionVideos(int collectionId) async {
    Logger.d('COLLECTION_SERVICE', '获取集合视频列表: $collectionId');

    final response = await _networkManager.get('$_basePath/$collectionId/videos');

    if (response['code'] == 200) {
      final data = response['data'] as List;
      return data
          .map((e) => CollectionVideoModel.fromJson(e as Map<String, dynamic>))
          .toList();
    } else {
      throw Exception(response['message'] ?? '获取视频列表失败');
    }
  }

  /// 更新视频排序
  Future<void> updateVideoOrder(int collectionId, List<int> videoIds) async {
    Logger.d('COLLECTION_SERVICE', '更新视频排序: $collectionId');

    final response = await _networkManager.put(
      '$_basePath/$collectionId/videos/order',
      data: videoIds,
    );

    if (response['code'] != 200) {
      throw Exception(response['message'] ?? '更新排序失败');
    }
  }

  /// 记录视频播放
  Future<void> recordVideoPlay(int videoId) async {
    Logger.d('COLLECTION_SERVICE', '记录视频播放: $videoId');

    await _networkManager.post('$_basePath/videos/$videoId/play');
  }

  // ==================== 白名单管理 ====================

  /// 添加白名单用户
  /// 
  /// [usernames] 用户名列表
  /// [expireTime] 过期时间（null表示永久）
  /// 
  /// 返回成功添加的数量
  Future<int> addWhitelistUsers({
    required int collectionId,
    required List<String> usernames,
    DateTime? expireTime,
  }) async {
    Logger.d('COLLECTION_SERVICE', '添加白名单用户: $collectionId, 数量: ${usernames.length}');

    final response = await _networkManager.post(
      '$_basePath/whitelist',
      data: {
        'collectionId': collectionId,
        'usernames': usernames,
        'expireTime': expireTime?.toIso8601String(),
      },
    );

    if (response['code'] == 200) {
      final count = response['data']['addedCount'] as int;
      Logger.d('COLLECTION_SERVICE', '成功添加 $count 个用户');
      return count;
    } else {
      throw Exception(response['message'] ?? '添加白名单失败');
    }
  }

  /// 移除白名单用户
  Future<void> removeWhitelistUser({
    required int collectionId,
    required int targetUserId,
  }) async {
    Logger.d('COLLECTION_SERVICE', '移除白名单用户: $collectionId, userId: $targetUserId');

    // delete方法不支持params，将参数拼接到URL
    final response = await _networkManager.delete(
      '$_basePath/whitelist?collectionId=$collectionId&targetUserId=$targetUserId',
    );

    if (response['code'] != 200) {
      throw Exception(response['message'] ?? '移除白名单失败');
    }
  }

  /// 获取白名单用户列表
  Future<PageResult<WhitelistUserModel>> getWhitelistUsers({
    required int collectionId,
    int page = 1,
    int pageSize = 20,
  }) async {
    Logger.d('COLLECTION_SERVICE', '获取白名单列表: $collectionId');

    final response = await _networkManager.get(
      '$_basePath/$collectionId/whitelist',
      params: {
        'page': page,
        'pageSize': pageSize,
      },
    );

    if (response['code'] == 200) {
      final data = response['data'] as Map<String, dynamic>;
      final records = (data['records'] as List)
          .map((e) => WhitelistUserModel.fromJson(e as Map<String, dynamic>))
          .toList();
      return PageResult(
        records: records,
        total: data['total'] as int,
        current: data['current'] as int,
        pages: data['pages'] as int,
      );
    } else {
      throw Exception(response['message'] ?? '获取白名单列表失败');
    }
  }

  // ==================== 文件上传 ====================

  /// 上传集合封面图（使用集合专用上传接口）
  /// 
  /// [collectionId] 集合ID，创建时可为null
  /// 返回上传后的图片URL
  /// 
  /// 存储路径: collection/{userId}/{collectionId}/cover.{ext}
  Future<String> uploadCoverImage(File imageFile, {int? collectionId}) async {
    Logger.d('COLLECTION_SERVICE', '上传集合封面，集合ID: $collectionId');
    try {
      final formData = FormData.fromMap({
        'file': await MultipartFile.fromFile(imageFile.path,
            filename: imageFile.path.split('/').last),
        if (collectionId != null) 'collectionId': collectionId,
      });

      final response = await _networkManager.post(
        '$_basePath/upload/cover',
        data: formData,
        contentType: 'multipart/form-data',
      );

      if (response['code'] == 200) {
        final url = response['data']?['url'] as String?;
        if (url != null && url.isNotEmpty) {
          Logger.d('COLLECTION_SERVICE', '封面上传成功: $url');
          return url;
        }
      }
      throw Exception(response['message'] ?? '上传封面失败：未获取到URL');
    } catch (e) {
      Logger.e('COLLECTION_SERVICE', '上传封面失败: $e');
      // 降级使用通用上传接口
      Logger.d('COLLECTION_SERVICE', '降级使用通用上传接口');
      final response = await ApiService().uploadImage(imageFile);
      final url = response['url'] as String?;
      if (url != null && url.isNotEmpty) {
        return url;
      }
      rethrow;
    }
  }

  /// 上传集合内视频（使用集合专用上传接口）
  /// 
  /// [collectionId] 集合ID
  /// 返回上传后的视频URL
  /// 
  /// 存储路径: collection/{userId}/{collectionId}/videos/{uuid}.{ext}
  Future<String> uploadVideo(File videoFile, {int? collectionId}) async {
    Logger.d('COLLECTION_SERVICE', '上传视频文件，集合ID: $collectionId');
    try {
      // 如果有集合ID，使用集合专用上传接口
      if (collectionId != null) {
        final formData = FormData.fromMap({
          'file': await MultipartFile.fromFile(videoFile.path,
              filename: videoFile.path.split('/').last),
          'collectionId': collectionId,
        });

        final response = await _networkManager.post(
          '$_basePath/upload/video',
          data: formData,
          contentType: 'multipart/form-data',
        );

        if (response['code'] == 200) {
          final url = response['data']?['url'] as String?;
          if (url != null && url.isNotEmpty) {
            Logger.d('COLLECTION_SERVICE', '视频上传成功: $url');
            return url;
          }
        }
        throw Exception(response['message'] ?? '上传视频失败：未获取到URL');
      }
      
      // 没有集合ID，使用通用上传接口
      final response = await ApiService().uploadVideo(videoFile);
      Logger.d('COLLECTION_SERVICE', '视频上传响应: $response');
      
      if (response['code'] == 200) {
        final url = response['data'] as String?;
        if (url != null && url.isNotEmpty) {
          Logger.d('COLLECTION_SERVICE', '视频上传成功: $url');
          return url;
        }
      }
      throw Exception(response['message'] ?? '上传视频失败：未获取到URL');
    } catch (e) {
      Logger.e('COLLECTION_SERVICE', '上传视频失败: $e');
      rethrow;
    }
  }

  // ==================== 标签管理 ====================

  /// 获取预设标签列表
  /// 
  /// 返回预设的标签列表供用户选择
  Future<List<String>> getPresetTags() async {
    Logger.d('COLLECTION_SERVICE', '获取预设标签');
    
    try {
      final response = await _networkManager.get('$_basePath/tags');
      
      if (response['code'] == 200) {
        final tags = (response['data'] as List?)?.map((e) => e.toString()).toList() ?? [];
        Logger.d('COLLECTION_SERVICE', '获取预设标签成功: ${tags.length}个');
        return tags;
      } else {
        // 如果接口失败，返回默认标签
        return _getDefaultTags();
      }
    } catch (e) {
      Logger.w('COLLECTION_SERVICE', '获取预设标签失败，使用默认标签: $e');
      return _getDefaultTags();
    }
  }

  /// 获取默认标签列表
  List<String> _getDefaultTags() {
    return [
      '教程',
      '技术',
      '生活',
      '娱乐',
      '游戏',
      '音乐',
      '美食',
      '旅行',
      '运动',
      '健身',
      '学习',
      '编程',
      '设计',
      '摄影',
      '汽车',
      '数码',
      '其他',
    ];
  }
}

/// 分页结果模型
class PageResult<T> {
  /// 数据列表
  final List<T> records;

  /// 总记录数
  final int total;

  /// 当前页码
  final int current;

  /// 总页数
  final int pages;

  PageResult({
    required this.records,
    required this.total,
    required this.current,
    required this.pages,
  });

  /// 是否有下一页
  bool get hasMore => current < pages;

  /// 是否为空
  bool get isEmpty => records.isEmpty;
}

